package cn.com.ethos.search.query;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;
import org.apache.lucene.store.FSDirectory;


public class QueryServer {
	
	private Logger logger   = Logger.getLogger(this.getClass());
	private boolean running = true;
	
	public Config config;
	ExecutorService executor;
		
	public void setUp(Config config){
		this.config   = config;
		this.executor = new ThreadPoolExecutor(
				this.config.getMinThreadsNum(),
				this.config.getMinThreadsNum(),
				30L, 
				TimeUnit.SECONDS,
				new LinkedBlockingQueue<Runnable>()
		);
	}
	
	public void service() {
		FSDirectory dir  		  = null;
		ServerSocket serverSocket = null;
		
		try {
			serverSocket = new ServerSocket(this.config.getPort());
			serverSocket.setReuseAddress(true);
			serverSocket.setSoTimeout(this.config.getTimeout());
			
		} catch(IOException ex) {
			logger.error("Bind server socket error,startup server failed.",ex);
			return;
		}
		
		try {
			dir = FSDirectory.getDirectory(this.config.getPath());
		} catch(IOException ex) {
			logger.error("Load directory faild,please check the path is an index path",ex);
			return;
		}
		
		while(running) {
			try {
				Socket socket  = serverSocket.accept();
				Worker worker  = new Worker(new SearchFacade(dir),socket);
				executor.execute(worker);
			}
			catch(java.net.SocketTimeoutException ex) {
				logger.debug("Idle time for " + this.config.getTimeout() / 1000 + "seconds.");
				continue;
			}
			catch(Exception ex) {
				logger.error("Execute request error,",ex);
				//System.exit(1);
			}
		}
		
		try{
			if(!serverSocket.isClosed()) {
				serverSocket.close();
			}
			logger.info("Closed server socket naturally");
		}catch(Exception ex) {
			logger.error("Can not close server socket naturally");
		}
		
	}
	
	public void shutDown() {
		this.running = false;
		this.executor.shutdown();	
	}
	
	protected void finalize() {
		this.shutDown();
	}
}
